package org.yx.service.smfr.save_production_order;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import com.fr.web.core.A.Q;
import org.dbist.dml.Query;
import org.yx.exception.BizException;
import org.yx.models.*;
import org.yx.service.bas.create_rule_code.BasCreateRuleCodeService;
import org.yx.utils.BaseService;
import org.yx.utils.FieldMap;

import com.xiaoleilu.hutool.collection.CollUtil;
import com.xiaoleilu.hutool.util.StrUtil;

/**
 * 保存生产工单信息
 *
 * @author zxw
 * @since 2018/04/19
 **/
public class SmfrSaveProductionOrderService extends BaseService {

    public SmfrSaveProductionOrderOut saveProductionOrder(SmfrSaveProductionOrderIn in) throws Exception {
        checkStringNotBlank(in, "matCode,matVer,moType,moStatus,pathCode");
        if (in.getMoQty().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BizException("SYS-0004", FieldMap.of("parameter", "moQty"));
        }

        Query query = new Query();
        query.addFilter("orgCode", in.getUserOrgCode());
        query.addFilter("matCode", in.getMatCode());
        query.addFilter("matVer", in.getMatVer());
        SbasProdMat prodMat = selectWithPk(SbasProdMat.class, in.getUserOrgCode(), in.getMatCode(), in.getMatVer());
        if (prodMat == null || 'D' == prodMat.getMatStatus()) {
            throw new BizException("SBAS-0001", "产品${matCode}不存在或已经删除。", FieldMap.of("matCode", in.getMatCode()));
        }
        query = new Query();
        query.addFilter("orgCode", in.getUserOrgCode());
        query.addFilter("matCode", in.getMatCode());
        query.addFilter("matVer", in.getMatVer());
        query.addFilter("pathCode", in.getPathCode());
        query.addFilter("pathStatus", "N");
        if (selectSize(SbasMatPth.class, query) == 0) {
            throw new BizException("SMFR-0016", "产品${matCode}未绑定工艺路线${pathCode}。", FieldMap.of("matCode", in.getMatCode()), FieldMap.of("pathCode", in.getPathCode()));
        }

        SmfrOrdDef ord = copyProperties(in, new SmfrOrdDef());
        ord.setMatCode(prodMat.getMatCode());
        ord.setMatVer(prodMat.getMatVer());
        ord.setMatDesc(prodMat.getMatDesc());
        ord.setUnit(prodMat.getUnit());
        ord.setOrgCode(in.getUserOrgCode());
        if (ord.getInQty() == null) {
            ord.setInQty(BigDecimal.ZERO);
        }
        if (ord.getOutQty() == null) {
            ord.setOutQty(BigDecimal.ZERO);
        }

        if (StrUtil.isBlank(in.getMo())) {
            //新增
            String mo = BasCreateRuleCodeService.createRuleCode("MO");
            ord.setMo(mo);
            insert(ord);
        } else {
            //修改
            updateOrder(ord);
        }

        SmfrSaveProductionOrderOut out = new SmfrSaveProductionOrderOut();
        out.setMo(ord.getMo());
        return out;
    }

    private void updateOrder(SmfrOrdDef newOrder) throws Exception {
        SmfrOrdDef oldOrder = selectOneLocked(SmfrOrdDef.class, newOrder.getOrgCode(), newOrder.getMo());
        if (oldOrder == null || "D".equals(oldOrder.getMoStatus())) {
            throw new BizException("SMFR-0004", new FieldMap("mo", newOrder.getMo()));
        }

        if (!oldOrder.getPathCode().equals(newOrder.getPathCode())) {
            //change process path
            changeProcessPath(oldOrder, newOrder.getPathCode());
        }
        copyProperties(newOrder, oldOrder);

        update(oldOrder);
    }

    private void changeProcessPath(SmfrOrdDef order, String toPathCode) throws Exception {
        Query queryOper = new Query();
        queryOper.addFilter("orgCode", order.getOrgCode());
        queryOper.addFilter("pathCode", toPathCode);
        //查询新工艺路线可用性
        SmfrProPth path = selectOne(SmfrProPth.class, queryOper);
        if (path == null || new Character('D').equals(path.getPathStatus())) {
            throw new BizException("SMFR-0002", new FieldMap("pathCode", toPathCode));
        }
        queryOper.addOrder("seqNum", true);

        List<SmfrPthOpr> pathOperList = selectList(SmfrPthOpr.class, queryOper);
        if (CollUtil.isEmpty(pathOperList)) {
            throw new BizException("SMFR-0005", new FieldMap("pathCode", toPathCode));
        }

        Query query = new Query(0, 1);
        query.addFilter("orgCode", order.getOrgCode());
        query.addFilter("mo", order.getMo());
        query.addFilter("status", "<>", "D");
        query.addOrder("operSeq", false);

        SmfrPsnSts psnSts = selectOne(SmfrPsnSts.class, query);
        Query query1 = new Query();
        query1.addFilter("orgCode", order.getOrgCode());
        query1.addFilter("mo", order.getMo());
        List<SmfrOrdOpr> oldOrdOprs = selectList(SmfrOrdOpr.class, query1);
        if (psnSts == null) {
            //没有在制记录时，直接插入订单工序表新记录
            if (!CollUtil.isEmpty(oldOrdOprs)) {
                deleteList(SmfrOrdOpr.class, query1);
            }

            List<SmfrOrdOpr> ordOprs = new ArrayList<SmfrOrdOpr>();
            for (SmfrPthOpr pathOpr : pathOperList) {
                SmfrOrdOpr ordOpr = new SmfrOrdOpr();
                copyProperties(pathOpr, ordOpr);
                ordOpr.setMo(order.getMo());
                ordOpr.setOperSeq(pathOpr.getSeqNum());

                ordOprs.add(ordOpr);
            }

            insertBatch(ordOprs);
        } else {
            //有在制记录，判断最远在制品工序之后能否支持修改
            int maxOperSeq = psnSts.getOperSeq();
            for (SmfrOrdOpr ordOpr : oldOrdOprs) {
                for (SmfrPthOpr oper : pathOperList) {
                    if (oper.getSeqNum().equals(ordOpr.getOperSeq())) {
                        if (!oper.getOper().equals(ordOpr.getOper())) {
                            if (oper.getSeqNum().intValue() <= maxOperSeq) {
                                //新工序有修改并且在在制之前的工序，不允许修改
                                throw new BizException("SMFR-0006", new FieldMap("psn", psnSts.getPsn()), new FieldMap("oper",
                                        psnSts.getOper()));
                            }
                        } else {
                            ordOpr.setOper(oper.getOper());

                            update(ordOpr, "oper");

                            pathOperList.remove(oper);
                        }
                    }
                }
            }

            //如果现在新工艺路线中工序还有剩余不存订单工序中，新增
            if (!CollUtil.isEmpty(pathOperList)) {
                List<SmfrOrdOpr> ordOprs = new ArrayList<SmfrOrdOpr>();
                for (SmfrPthOpr pathOpr : pathOperList) {
                    SmfrOrdOpr ordOpr = new SmfrOrdOpr();
                    copyProperties(pathOpr, ordOpr);
                    ordOpr.setMo(order.getMo());
                    ordOpr.setOperSeq(pathOpr.getSeqNum());

                    ordOprs.add(ordOpr);
                }

                insertBatch(ordOprs);
            }
        }
    }
}